/*
 * Notepad.java  0.4.0 / Oct 24, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
package com.cute4j.demos.notepad;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.Locale;

import com.cute4j.swing.CheckBoxMenuItem;
import com.cute4j.swing.FileChooser;
import com.cute4j.swing.FontChooser;
import com.cute4j.swing.Frame;
import com.cute4j.swing.KeyStroke;
import com.cute4j.swing.Menu;
import com.cute4j.swing.MenuBar;
import com.cute4j.swing.MenuItem;
import com.cute4j.swing.OptionPane;
import com.cute4j.swing.RadioButtonMenuItem;
import com.cute4j.swing.SelectableGroup;
import com.cute4j.swing.StatusBar;
import com.cute4j.swing.Swing;
import com.cute4j.swing.TextArea;
import com.cute4j.swing.events.ActionEvent;
import com.cute4j.swing.events.ActionListener;
import com.cute4j.swing.events.WindowEvent;
import com.cute4j.swing.graphics.Font;
import com.cute4j.swing.print.Printer;
import com.cute4j.swingx.StyleMenu;
import com.cute4j.swingx.ThemeMenu;
import com.cute4j.swingx.actions.AboutQtAction;
import com.cute4j.swingx.actions.AboutCute4jAction;
import com.cute4j.swingx.actions.ExitAction;
import com.cute4j.swingx.actions.NewAction;
import com.cute4j.swingx.actions.OpenAction;
import com.cute4j.swingx.actions.PageSetupAction;
import com.cute4j.swingx.actions.PrintAction;
import com.cute4j.swingx.actions.SaveAction;
import com.cute4j.swingx.actions.SaveAsAction;
import com.cute4j.swingx.actions.TextComponentCopyAction;
import com.cute4j.swingx.actions.TextComponentCutAction;
import com.cute4j.swingx.actions.TextComponentDeleteAction;
import com.cute4j.swingx.actions.TextComponentPasteAction;
import com.cute4j.swingx.actions.TextComponentRedoAction;
import com.cute4j.swingx.actions.TextComponentSelectAllAction;
import com.cute4j.swingx.actions.TextComponentUndoAction;

/**
 * Cute4j Notepad.
 *
 * @author Slobodan Vrkacevic
 * @version 0.4.0
 */
public final class Notepad extends Frame {

// Private Fields. -------------------------------------------------------------

  private RadioButtonMenuItem rbmiEnglish;
  private RadioButtonMenuItem rbmiSerbian;
  private final TextArea textArea;
  private final StatusBar statusBar;
  private File currentFile;
  private Printer printer;

// Public Constructors. --------------------------------------------------------

  /**
   * Constructs new Notepad object.
   */
  public Notepad() {
    super("Untitled - Cute4j Notepad");
    setIconImage(Swing.crateImage(getClass().getResource("Notepad.png")));
    setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
    setSize(640, 480);
    textArea = new TextArea();
    add(textArea);
    buildMenuBar();
    statusBar = setStatusBar(new StatusBar());
    statusBar.setVisible(false);
    Locale.setDefault(Locale.US);
    Swing.setLocale(Locale.US);
    setDefaultResourceBundleName();
  }

// Overridden Methods. ---------------------------------------------------------

  /**
   * {@inheritDoc}
   */
  protected void processWindowEvent(WindowEvent event) {
    super.processWindowEvent(event);
    if (event.getID() == WindowEvent.WINDOW_CLOSING) {
      exit();
    }
  }

// Package-Private Methods. ----------------------------------------------------

  void performNew() {
    if (textArea.isModified()) {
      switch (warn()) {
        case OptionPane.YES_OPTION:
          if (currentFile == null) {
            if (!saveAs()) { // NOPMD
              return;
            }
          }
          store();
          break;
        case OptionPane.NO_OPTION:
          break;
        default:
          return;
      }
    }
    textArea.clearText();
    setCurrentFile(null);
  }

  void performOpen() {
    if (textArea.isModified()) {
      switch (warn()) {
        case OptionPane.YES_OPTION:
          if (currentFile == null) {
            if (!saveAs()) { // NOPMD
              return;
            }
          }
          store();
          break;
        case OptionPane.NO_OPTION:
          break;
        default:
          return;
      }
    }
    String fileName = FileChooser.getOpenFileName(Notepad.this, null, null,
                                                  "Text Documents (*.txt)",
                                                  null);
    if (fileName != null) {
      setCurrentFile(fileName);
      load();
    }
  }

  void performSave() {
    if (currentFile == null) {
      if (!saveAs()) { // NOPMD
        return;
      }
    }
    store();
  }

  void performSaveAs() {
    if (saveAs()) {
      store();
    }
  }

  void performPageSetup() {
    if (printer == null) {
      printer = new Printer();
    }
    printer.pageDialog();
  }

  void performPrint() {
    if (printer == null) {
      printer = new Printer();
    }
    if (printer.printerDialog()) {
      textArea.print(printer);
    }
  }

  void performExit() {
    exit();
  }

  void performTimeDate() {
    textArea.insertText(new Date().toString());
  }

  void performWordWrap() {
    textArea.setWrapText(!textArea.isWrapText());
  }

  void performFont() {
    Font font = FontChooser.getFont(Notepad.this, textArea.getFont());
    if (font != null) {
      textArea.setFont(font);
    }
  }

  void performStatusBar() {
    statusBar.setVisible(!statusBar.isVisible());
  }

  void performEnglish() {
    if (rbmiEnglish.isSelected()) {
      Swing.removeTranslation();
      Swing.setLocale(Locale.US);
      updateLocalization();
    }
  }

  void performSerbian() {
    if (rbmiSerbian.isSelected()) {
      Swing.setTranslation("../trans/cute4j_sr.qm"); // TODO: finish
      Swing.setLocale(new Locale("sr"));
      updateLocalization();
    }
  }

// Private Methods. ------------------------------------------------------------

  private void buildMenuBar() {
    MenuBar menuBar = setMenuBar(new MenuBar());
    Menu menu = menuBar.add(new Menu("&File"));
    menu.add(new MenuItem(new NewAction() {
      public void actionPerformed(ActionEvent e) {
        performNew();
      }
    }));
    menu.add(new MenuItem(new OpenAction() {
      public void actionPerformed(ActionEvent e) {
        performOpen();
      }
    }));
    menu.add(new MenuItem(new SaveAction() {
      public void actionPerformed(ActionEvent e) {
        performSave();
      }
    }));
    menu.add(new MenuItem(new SaveAsAction() {
      public void actionPerformed(ActionEvent e) {
        performSaveAs();
      }
    }));
    menu.addSeparator();
    menu.add(new MenuItem(new PageSetupAction() {
      public void actionPerformed(ActionEvent e) {
        performPageSetup();
      }
    }));
    menu.add(new MenuItem(new PrintAction() {
      public void actionPerformed(ActionEvent e) {
        performPrint();
      }
    }));
    menu.addSeparator();
    menu.add(new MenuItem(new ExitAction() {
      public void actionPerformed(ActionEvent e) {
        performExit();
      }
    }));
    // Edit Menu
    menu = menuBar.add(new Menu("&Edit"));
    menu.add(new MenuItem(new TextComponentUndoAction(textArea)));
    menu.add(new MenuItem(new TextComponentRedoAction(textArea)));
    menu.addSeparator();
    menu.add(new MenuItem(new TextComponentCutAction(textArea)));
    menu.add(new MenuItem(new TextComponentCopyAction(textArea)));
    menu.add(new MenuItem(new TextComponentPasteAction(textArea)));
    menu.add(new MenuItem(new TextComponentDeleteAction(textArea)));
    menu.addSeparator();
    menu.add(new MenuItem(new TextComponentSelectAllAction(textArea)));
    MenuItem menuItem = menu.add(new MenuItem("Time/&Date"));
    menuItem.setAccelerator(KeyStroke.getKeyStroke("F5"));
    menuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        performTimeDate();
      }
    });
    // Format Menu
    menu = menuBar.add(new Menu("F&ormat"));
    menuItem = menu.add(new CheckBoxMenuItem("&Wrap Word"));
    menuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        performWordWrap();
      }
    });
    menuItem = menu.add(new MenuItem("&Font..."));
    menuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        performFont();
      }
    });
    // View Menu
    menu = menuBar.add(new Menu("&View"));
    menuItem = menu.add(new CheckBoxMenuItem("&Status Bar"));
    menuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        performStatusBar();
      }
    });
    // Settings Menu
    menu = menuBar.add(new Menu("&Settings"));
    menu.add(new StyleMenu());
    menu.add(new ThemeMenu());
    SelectableGroup sgLanguages = new SelectableGroup();
    menu = menu.add(new Menu("&Language"));
    rbmiEnglish = new RadioButtonMenuItem("&English");
    rbmiEnglish.setSelected(true);
    sgLanguages.add(rbmiEnglish);
    menuItem = menu.add(rbmiEnglish);
    menuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        performEnglish();
      }
    });
    rbmiSerbian = new RadioButtonMenuItem("&Српски");
    sgLanguages.add(rbmiSerbian);
    menuItem = menu.add(rbmiSerbian);
    menuItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        performSerbian();
      }
    });
    // Help Menu
    menuBar.addSeparator();
    menu = menuBar.add(new Menu("&Help"));
    menu.add(new MenuItem(new AboutCute4jAction()));
    menu.add(new MenuItem(new AboutQtAction()));
  }

  private void setCurrentFile(String fileName) {
    if (fileName == null) {
      currentFile = null;
      setTitle("Untitled - Cute4j Notepad");
    } else {
      currentFile = new File(fileName);
      setTitle(currentFile.getName() + " - Cute4j Notepad");
    }
  }

  private void load() {
    FileReader fr = null;
    try {
      fr = new FileReader(currentFile);
      textArea.read(fr);
    } catch (IOException ioe) {
      OptionPane.showErrorMessage(this, "Error loading file", "Cute4j Notepad",
                                  OptionPane.OK_OPTION);
    } finally {
      if (fr != null) {
        try {
          fr.close();
        } catch (IOException ioe) { // NOPMD
          // empty catch block
        }
      }
    }
  }

  private void store() {
    FileWriter fw = null;
    try {
      fw = new FileWriter(currentFile);
      textArea.write(fw);
    } catch (IOException ioe) {
      OptionPane.showErrorMessage(this, "Error storing file", "Cute4j Notepad",
                                  OptionPane.OK_OPTION);
    } finally {
      if (fw != null) {
        try {
          fw.close();
        } catch (IOException ioe) { // NOPMD
          // empty catch block
        }
      }
    }
  }

  private boolean saveAs() {
    String dir = null;
    if (currentFile != null) {
      dir = currentFile.toString();
    }
    String fileName = FileChooser.getSaveFileName(this, "Save As", dir,
                                                  "Text Documents (*.txt)",
                                                  null);
    if (fileName != null) {
      setCurrentFile(fileName);
      return true;
    }
    return false;
  }

  private int warn() {
    StringBuffer sb = new StringBuffer(localizeString("The text in the ")); 
    if (currentFile == null) {
      sb.append("Untitled");
    } else {
      sb.append(currentFile.getName());
    }
    sb.append(localizeString(" has changed.\n\nDo you want to save changes?"));
    return OptionPane.showWarningMessage(this, sb.toString(), "Cute4j Notepad",
                                         OptionPane.YES_NO_CANCEL_OPTIONS);
  }

  private void exit() {
    if (textArea.isModified()) {
      switch (warn()) {
        case OptionPane.YES_OPTION:
          if (currentFile == null) {
            if (!saveAs()) { // NOPMD
              return;
            }
          }
          store();
          break;
        case OptionPane.NO_OPTION:
          break;
        default:
          return;
      }
    }
    Swing.stopEventLoop();
  }

// Main Method. ----------------------------------------------------------------

  /**
   * Starts the Cute4j Notepad.
   *
   * @param args the application arguments
   */
  public static void main(String[] args) {
    Notepad notepad = new Notepad();
    notepad.setVisible(true);
    Swing.startEventLoop();
  }

}
